package cn.lisens.demo;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;

import javax.net.ssl.SSLException;
import javax.swing.event.ListSelectionEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

import cn.lisens.demo.config.WebClientProperties;
import cn.lisens.demo.model.Customer;
import cn.lisens.demo.service.AuthorizationClient;
import cn.lisens.demo.service.AuthorizationFilterFunction;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;

public class TestWebClient {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	public WebClient.Builder webClientBuilder() {
		 
		HttpClient httpClient = HttpClient.create()
//				.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) // 连接超时
				.responseTimeout(Duration.ofSeconds(4));// 总请求超时
                
		return WebClient.builder()
				.baseUrl("http://dev.lisens.cn:8099/web")
				.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024))
				.clientConnector(new ReactorClientHttpConnector(httpClient));
	}
	
	private final WebClient webClient;
	private static String JSESSIONID = null;

	public TestWebClient() throws SSLException {
        
		this.webClient = webClientBuilder()
				.filter(addTokenFilter())
				.filter(renewTokenFilter())
				.filter(logRequest())
				.build();
	}
	private ExchangeFilterFunction logRequest() {
        return (clientRequest, next) -> {
        	System.err.println("------------日志开始输出------------");
            logger.info("请求: {} {}", clientRequest.method(), clientRequest.url());
            clientRequest.headers()
                    .forEach((name, values) -> values.forEach(value -> logger.info("header:{}={}", name, value)));
            clientRequest.cookies()
            		.forEach((name, values) -> values.forEach(value -> logger.info("cookies:{}={}", name, value)));
            System.err.println("------------日志输出结束------------");
            return next.exchange(clientRequest);
        };
    }
	public ExchangeFilterFunction addTokenFilter() {
		return ExchangeFilterFunction.ofRequestProcessor(req -> {
			return Mono.just(ClientRequest.from(req).cookie("JSESSIONID", JSESSIONID).build());
		});
	}
	
	public ExchangeFilterFunction renewTokenFilter() {
	    return (request, next) -> next.exchange(request).flatMap(response -> {
	    	if (response.statusCode().equals(HttpStatus.FOUND) && "/web/login".equals(response.headers().header("Location").get(0))) {
	    		System.err.println("需要登录");
	    		return response.releaseBody()
	    				.then(newToken())
	                    .flatMap(token -> {
	                    	System.err.println(token);
//	                    	request.cookies().add("bb", token);
//	                    	ClientRequest newRequest2 = ClientRequest.from(request).cookie("JSESSIONID", token).build();
//	                    	return next.exchange(newRequest2);
	                    	ClientRequest newRequest = ClientRequest.from(request)
	                        		.cookies(cookies -> cookies.put("JSESSIONID", Arrays.asList(token)))
	                        		.build();
	                        return next.exchange(newRequest);
	                    });
	    	}else {
	    		return Mono.just(response);
	    	}
	    });
	}
	
	public Mono<String> newToken(){
		return webClientBuilder()
				.filter(logRequest())
				.build()
				.post()
				.uri("/login")
				.body(BodyInserters.fromFormData("username", "admin").with("password", "lyxx"))
				.exchangeToMono(response -> {
					if (response.statusCode().equals(HttpStatus.FOUND)) {
						if(response.cookies().get("JSESSIONID").get(0) != null) {
							JSESSIONID = response.cookies().get("JSESSIONID").get(0).getValue();
							return Mono.just(JSESSIONID);
						}
					}
					return Mono.just("");
				});
	}
	public static void main(String[] args) throws SSLException {
		TestWebClient client = new TestWebClient();
		List<Customer> list = client.webClient
		.post()
		.uri("/customer/listData")
        .accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .bodyToFlux(Customer.class)
        .collectList()
        .block();
		System.err.println(list.size());
	}
}
